package main

import (
	"encoding/json"
	"fmt"

	"github.com/hyperledger/fabric-chaincode-go/shim"
	pb "github.com/hyperledger/fabric-protos-go/peer"
)

// Asset 定义资产结构体
type Asset struct {
	ID    string `json:"id"`
	Name  string `json:"name"`
	Info  string `json:"info"`
	Owner string `json:"owner"`
}

// AssetChaincode 定义链码结构体
type AssetChaincode struct {
}

// Init 链码初始化方法
func (t *AssetChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
	return shim.Success(nil)
}

// Invoke 链码调用方法
func (t *AssetChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
	fn, args := stub.GetFunctionAndParameters()
	var result pb.Response
	switch fn {
	case "CreateAsset":
		result = t.createAsset(stub, args)
	case "TransferAsset":
		result = t.transferAsset(stub, args)
	default:
		result = shim.Error("Invalid function name")
	}
	return result
}

// createAsset 创建资产方法
func (t *AssetChaincode) createAsset(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	if len(args) != 4 {
		return shim.Error("Incorrect number of arguments. Expecting 4")
	}
	id := args[0]
	name := args[1]
	info := args[2]
	owner := args[3]

	// 检查资产是否已存在
	assetJSON, err := stub.GetState(id)
	if err != nil {
		return shim.Error(fmt.Sprintf("Failed to read from world state: %s", err.Error()))
	}
	if assetJSON != nil {
		return shim.Error(fmt.Sprintf("Asset %s already exists", id))
	}

	// 创建新资产
	asset := Asset{
		ID:    id,
		Name:  name,
		Info:  info,
		Owner: owner,
	}
	assetJSON, err = json.Marshal(asset)
	if err != nil {
		return shim.Error(fmt.Sprintf("Failed to marshal asset: %s", err.Error()))
	}

	// 将资产保存到账本
	err = stub.PutState(id, assetJSON)
	if err != nil {
		return shim.Error(fmt.Sprintf("Failed to put asset to world state: %s", err.Error()))
	}

	return shim.Success(nil)
}

// transferAsset 资产转移方法
func (t *AssetChaincode) transferAsset(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	if len(args) != 2 {
		return shim.Error("Incorrect number of arguments. Expecting 2")
	}
	id := args[0]
	newOwner := args[1]

	// 检查资产是否存在
	assetJSON, err := stub.GetState(id)
	if err != nil {
		return shim.Error(fmt.Sprintf("Failed to read from world state: %s", err.Error()))
	}
	if assetJSON == nil {
		return shim.Error(fmt.Sprintf("Asset %s does not exist", id))
	}

	// 解析资产信息
	var asset Asset
	err = json.Unmarshal(assetJSON, &asset)
	if err != nil {
		return shim.Error(fmt.Sprintf("Failed to unmarshal asset: %s", err.Error()))
	}

	// 更新资产所有者
	asset.Owner = newOwner
	assetJSON, err = json.Marshal(asset)
	if err != nil {
		return shim.Error(fmt.Sprintf("Failed to marshal asset: %s", err.Error()))
	}

	// 将更新后的资产保存到账本
	err = stub.PutState(id, assetJSON)
	if err != nil {
		return shim.Error(fmt.Sprintf("Failed to put asset to world state: %s", err.Error()))
	}

	return shim.Success(nil)
}
